# from webapp2_extras.appengine.auth.models import User
from google.appengine.ext import ndb


class AppSetting(ndb.Model):
    """
    Application Settings' model
    """
    #: Modification date
    updated = ndb.DateTimeProperty(auto_now=True)
    #: App has done bootstrapping data
    bootstrapped = ndb.BooleanProperty('btd', default=False)
    #: App has started bootstrapping data
    bootstrap_started = ndb.BooleanProperty('bts')


class Channel(ndb.Model):
    """
    Channel API Client Identifier model
    """
    #: Creation date.
    created = ndb.DateTimeProperty('c', auto_now_add=True)
    #: Modification date.
    updated = ndb.DateTimeProperty('u', auto_now=True)
    #: client id
    cid = ndb.StringProperty()


class User(ndb.Model):
    """
        Universal user model. Can be used with App Engine's default users API,
        own auth or third party authentication methods (OpenID, OAuth etc).
        based on https://gist.github.com/kylefinley
    """
    #: Creation date.
    created = ndb.DateTimeProperty('c', auto_now_add=True)
    #: Modification date.
    updated = ndb.DateTimeProperty('u', auto_now=True)
    #: User ID from users object
    # userid = ndb.StringProperty('uid')
    #: User defined unique name, also used as key_name.
    # Not used by OpenID
    # username = ndb.StringProperty()
    display = ndb.StringProperty('ds')
    #: User Name
    name = ndb.StringProperty('nm')
    #: User Last Name
    # last_name = ndb.StringProperty()
    #: User email
    email = ndb.StringProperty('em')
    #: Hashed password. Only set for own authentication.
    # Not required because third party authentication
    # doesn't use password.
    # password = ndb.StringProperty()
    #: User Country
    country = ndb.StringProperty('ct')
    #: User Province, only available if country is Indonesia
    province = ndb.StringProperty('pv')
    #: User Address
    address = ndb.StringProperty('ad')
    #: User Phone Number
    phone = ndb.StringProperty('ph')
    #: User Date of Birth
    dob = ndb.DateProperty()
    #: User Gender
    gender = ndb.StringProperty('gd')
    #: Community Identity, could be students/lecturer id number
    inumber = ndb.StringProperty('in')
    #: User Photo
    img = ndb.BlobKeyProperty()
    #: User Bio
    bio = ndb.StringProperty()
    #: User Rating, bigger number is better
    rating = ndb.IntegerProperty('rt', default=0)
    #: Rate count
    rate_count = ndb.IntegerProperty('rc', default=0)
    #: Account activation verifies email
    # activated = ndb.BooleanProperty(default=False)

    # def to_dict(self):
    #     return dict([(p, unicode(getattr(self, p))) for p in self.properties()])

    @classmethod
    def get_by_email(cls, email):
        """Returns a user object based on an email.

        :param email:
            String representing the user email. Examples:

        :returns:
            A user object.
        """
        return cls.query(cls.email == email).get()


class Admin(ndb.Model):
    """Admin Model"""
    #: Creation date.
    # created = ndb.DateTimeProperty(auto_now_add=True)
    #: Modification date.
    # updated = ndb.DateTimeProperty(auto_now=True)
    #: User property
    # user = ndb.KeyProperty(kind=User)
    #: Admin id
    # admin_id = ndb.StringProperty()
    #: Active
    active = ndb.BooleanProperty()


class Item(ndb.Model):
    """
        Items model
    """
    #: Creation date.
    created = ndb.DateTimeProperty('c', auto_now_add=True)
    #: Modification date.
    updated = ndb.DateTimeProperty('u', auto_now=True)
    #: Expire date.
    expire = ndb.DateTimeProperty('e')
    #: Expired.
    expired = ndb.BooleanProperty('ed', default=False)
    #: Active
    active = ndb.BooleanProperty('ac', default=True)
    #: Item title.
    title = ndb.StringProperty('t')
    #: Item Description
    desc = ndb.JsonProperty('ds')
    #: Item Price
    price = ndb.IntegerProperty('p')
    #: Item Image
    img = ndb.BlobKeyProperty(repeated=True)
    #: Private
    private = ndb.BooleanProperty('pr', default=False)
    #: Visible User
    vis_user = ndb.KeyProperty('vu', kind=User, repeated=True)
    #: Item Status
    status = ndb.IntegerProperty('st')
    #: Item Rating, bigger number is better
    rating = ndb.FloatProperty('rt', default=0)
    #: Rate count
    rate_count = ndb.IntegerProperty('rc', default=0)
    #: Views
    views = ndb.IntegerProperty('v', default=0)
    #: Item's category
    categories = ndb.StringProperty('ct', repeated=True)

    @classmethod
    def get_latest(cls):
        return cls.query().order(-cls.created).fetch(5)

    @classmethod
    def get_popular(cls):
        return cls.query().order(-cls.rating).fetch(5)


class Message(ndb.Model):
    """
        Message Model
    """
    #: Creation date.
    created = ndb.DateTimeProperty('c', auto_now_add=True)
    #: Sender
    sender = ndb.KeyProperty('s', kind=User)
    #: Receiver
    receiver = ndb.KeyProperty('r', kind=User)
    #: Message Title
    title = ndb.StringProperty('t')
    #: Item
    item = ndb.KeyProperty('i', kind=Item)
    #: Content
    content = ndb.JsonProperty('m')
    #: Read
    read = ndb.BooleanProperty(default=False)


class Feedback(ndb.Model):
    """
        Item's Feedback model
    """
    #: Creation date.
    created = ndb.DateTimeProperty(auto_now_add=True)
    #: Modification date.
    updated = ndb.DateTimeProperty(auto_now=True)
    #: Content
    content = ndb.StringProperty()
    #: User who made the Feedback
    user = ndb.KeyProperty(kind=User)
    #: Helpfulness of Feedback
    rating = ndb.IntegerProperty(repeated=True, choices=[-1, 0, 1])


class BaseLog(ndb.Model):
    user = ndb.KeyProperty(kind=User)
    uastring = ndb.StringProperty()
    ip = ndb.StringProperty()
    timestamp = ndb.StringProperty()


class LogVisit(BaseLog):
    """Log User Visit"""


class LogItems(BaseLog):
    item = ndb.KeyProperty(kind=Item)


class LogUserSetting(BaseLog):
    """Log Changes to User Setting"""


class LogEmail(ndb.Model):
    sender = ndb.StringProperty(
        required=True)
    to = ndb.StringProperty(
        required=True)
    subject = ndb.StringProperty(
        required=True)
    body = ndb.TextProperty()
    when = ndb.DateTimeProperty()
